package com.example.shangyf.scene;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.Toast;

import com.example.shangyf.scene.bean.CoordinatesBean;
import com.example.shangyf.scene.event.BubbleCoordinateEvent;
import com.example.shangyf.scene.event.PathCoordinateEvent;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Samuel.shang on 2018/11/14.
 */
public class SceneView extends View {
    private static final String TAG = SceneView.class.getSimpleName();
    //场景图片
    private Bitmap sceneBitmap;

    //使用双缓冲
    private Canvas bufferCanvas;
    private Bitmap bufferBitmap;

    //初始缩放比例
    private float mInitScale = 0;
    private Matrix matrix = null;
    private float[] values = new float[9];

    //气泡的图片
    private Bitmap bubbleBitmap;
    //气泡文字的画笔
    private Paint paint;
    //气泡对应的坐标
    private List<BubbleCoordinateEvent> bubbleCoordinateList;
    //文字的宽高
    private int x;
    private int y;
    //点击区域
    private List<BubbleCoordinateEvent> pathCoordinateList;
    private ArrayList<PathCoordinateEvent> pathCoordinateEventList;
    private Paint paintPath;

    //手的图片
    private Bitmap handBitmap;
    //手指的坐标
    private int handX = -1;
    private int handY = -1;
    //记录当前手指移动的次数
    private int count = 0;
    //时候停止动画
    private HandThread handThread;

    // true:正在缩放
    private boolean isScale;
    // 是否多个手指
    private boolean pointer;
    private int lastX;
    private int lastY;
    private int downX;
    private int downY;

    private OnSceneClickListener onSceneClickListener;

    private static final int SCENE_HAND_UP = 0x001;
    private static final int SCENE_HAND_DOWN = 0x002;

    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SCENE_HAND_UP:
                    handY -= 2;
                    count++;
                    Log.d("SCENE", "======" + handY);
                    doSomething();
                    invalidate();
                    if (count == 5) {
                        count = 0;
                        handler.sendEmptyMessageDelayed(SCENE_HAND_DOWN, 100);
                    } else {
                        handler.sendEmptyMessageDelayed(SCENE_HAND_UP, 100);
                    }
                    break;
                case SCENE_HAND_DOWN:
                    Log.d("SCENE", "======" + handY);
                    handY += 2;
                    count++;
                    doSomething();
                    invalidate();
                    if (count == 5) {
                        count = 0;
                        handler.sendEmptyMessageDelayed(SCENE_HAND_UP, 100);
                    } else {
                        handler.sendEmptyMessageDelayed(SCENE_HAND_DOWN, 100);
                    }

                    break;
            }

        }
    };

    public SceneView(Context context) {
        this(context, null);
    }

    public SceneView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SceneView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    //初始化
    private void init(Context context) {
        matrix = new Matrix();
        pathCoordinateEventList = new ArrayList<>();


        Drawable drawable = context.getDrawable(R.drawable.map_content);
        bubbleBitmap = drawableToBitmap(drawable);

        Drawable handDrawable = context.getDrawable(R.drawable.ic_hand);
        handBitmap = drawableToBitmap(handDrawable);

        paint = new Paint();
        paint.setTextAlign(Paint.Align.LEFT);
        paint.setStrokeWidth(dip2px(context, 1));
        paint.setTextSize(dip2px(context, 10));
        paint.setColor(Color.BLACK);
        paint.setAntiAlias(true);

        paintPath = new Paint();
        paintPath.setAntiAlias(true);
        paintPath.setColor(Color.parseColor("#ff0000"));
        paintPath.setStrokeWidth(4.0f);
        paintPath.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (bufferBitmap == null) {
            return;
        }
        canvas.drawBitmap(bufferBitmap, matrix, null);
    }

    private void initCanvas() {
        if (sceneBitmap == null) {
            return;
        }
        bufferBitmap = Bitmap.createBitmap(sceneBitmap.getWidth(),
                sceneBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        bufferCanvas = new Canvas(bufferBitmap);
    }

    //初始化场景图片的位置，将场景居中
    private void initSceneLocation() {
        if (sceneBitmap == null) {
            return;
        }
        //计算场景图片的大小
        int width = sceneBitmap.getWidth();
        int height = sceneBitmap.getHeight();
        if (width >= getWidth() && height >= getHeight()) {
            //设置当前的缩放
            mInitScale = 1;
            matrix.postScale(mInitScale, mInitScale);
        } else {
            float xScale = getWidth() / width;
            float yScale = getHeight() / height;
            mInitScale = Math.max(xScale, yScale);
            matrix.postScale(mInitScale, mInitScale);
        }
        //将场景居中设置
        float currentSeatBitmapHeight = sceneBitmap.getHeight() * getMatrixScaleY();
        float currentSeatBitmapWidth = sceneBitmap.getWidth() * getMatrixScaleX();
        float startX = -(currentSeatBitmapWidth - getWidth()) / 2;
        float startY = -(currentSeatBitmapHeight - getHeight()) / 2;
        matrix.postTranslate(startX, startY);
    }

    private void doSomething() {
        drawScene();
        drawPath();
        drawBubbleText();
        drawHand();
        invalidate();
    }

    //画场景图片
    private void drawScene() {
        bufferCanvas.drawBitmap(sceneBitmap, 0, 0, null);
    }

    //画气泡
    private void drawBubbleText() {
        if (bufferCanvas != null && bubbleBitmap != null &&
                bubbleCoordinateList != null && bubbleCoordinateList.size() > 0) {
            for (BubbleCoordinateEvent bubbleCoordinateEvent : bubbleCoordinateList) {
                String content = bubbleCoordinateEvent.getContent();
                List<CoordinatesBean> coordinatesList = bubbleCoordinateEvent.getCoordinatesBeanList();
                if (coordinatesList != null && coordinatesList.size() > 0) {
                    //x  (图片的宽-文字的宽)/2 为文字开始的位置
                    CoordinatesBean coordinates = coordinatesList.get(0);
                    //气泡
                    bufferCanvas.drawBitmap(bubbleBitmap,
                            coordinates.getX() - bubbleBitmap.getWidth() / 2,
                            coordinates.getY() - bubbleBitmap.getHeight(), null);
                    if (content.length() > 10) {//换行处理
                        String split1 = content.substring(0, 10);
                        String split2 = content.substring(10, content.length());
                        Rect bounds = new Rect();
                        paint.getTextBounds(split1, 0, split1.length(), bounds);
                        //获取文字的宽和高
                        x = bounds.width();
                        y = bounds.height();
                        //画前10个文字
                        bufferCanvas.drawText(split1, coordinates.getX() - bubbleBitmap.getWidth() / 2
                                        + (bubbleBitmap.getWidth() - x) / 2,
                                coordinates.getY() - (bubbleBitmap.getHeight() / 2) - 30, paint);
                        bufferCanvas.drawText(split2, coordinates.getX() - bubbleBitmap.getWidth() / 2
                                        + (bubbleBitmap.getWidth() - x) / 2,
                                coordinates.getY() - (bubbleBitmap.getHeight() / 4) - 30, paint);
                    } else {
                        Rect bounds = new Rect();
                        paint.getTextBounds(content, 0, content.length(), bounds);
                        //获取文字的宽和高
                        x = bounds.width();
                        y = bounds.height();
                        //画前10个文字
                        bufferCanvas.drawText(content, coordinates.getX() - bubbleBitmap.getWidth() / 2
                                        + (bubbleBitmap.getWidth() - x) / 2,
                                coordinates.getY() - bubbleBitmap.getHeight() / 2 - y / 2, paint);
                    }
                }
            }
        }
    }

    //画点击区域
    private void drawPath() {
        if (pathCoordinateEventList.size() > 0) {
            pathCoordinateEventList.clear();
        }
        if (pathCoordinateList != null && pathCoordinateList.size() > 0) {
            for (int i = 0; i < pathCoordinateList.size(); i++) {
                BubbleCoordinateEvent bubbleCoordinateEvent = pathCoordinateList.get(i);
                PathCoordinateEvent pathCoordinateEvent = new PathCoordinateEvent();
                pathCoordinateEvent.setActivation(bubbleCoordinateEvent.getActivation());
                Path path = new Path();
                List<CoordinatesBean> coordinatesList = bubbleCoordinateEvent.getCoordinatesBeanList();
                if (coordinatesList != null && coordinatesList.size() > 0) {
                    for (int j = 0; j < coordinatesList.size(); j++) {
                        CoordinatesBean coordinatesBean = coordinatesList.get(j);
                        if (j == 0) {
                            path.moveTo(coordinatesBean.getX(), coordinatesBean.getY());
                        } else {
                            path.lineTo(coordinatesBean.getX(), coordinatesBean.getY());
                        }
                    }
                }
                path.close();
                pathCoordinateEvent.setPath(path);
                pathCoordinateEventList.add(pathCoordinateEvent);
            }
        }
        for (int i = 0; i < pathCoordinateEventList.size(); i++) {
            bufferCanvas.drawPath(pathCoordinateEventList.get(i).getPath(), paintPath);
        }
    }

    //画手
    public void drawHand() {
        if (handX != -1 && handY != -1 && handBitmap != null) {
            bufferCanvas.drawBitmap(handBitmap, handX, handY, null);
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        gestureDetector.onTouchEvent(event);
        scaleGestureDetector.onTouchEvent(event);
        if (event.getPointerCount() > 1) {
            pointer = true;
        }
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                downX = x;
                downY = y;
                pointer = false;
                break;
            case MotionEvent.ACTION_MOVE: // 移动的时候需要进行边缘检测
                if (!isScale) {
                    int dx = Math.abs(x - downX);
                    int dy = Math.abs(y - downY);
                    Log.d(TAG, dx + "========dx");
                    Log.d(TAG, dy + "========dy");
                    if (dx > 10 && dy > 10 && !pointer) {
                        dx = x - lastX;
                        dy = y - lastY;
                        //matrix.postTranslate(dx, dy);
                        moveToEdge(dx, dy);
                        invalidate();
                    }
                }
                break;
            case MotionEvent.ACTION_UP://这里需要滑动一段继续滑动

                break;
        }
        lastX = x;
        lastY = y;
        return true;
    }

    //前提是图片必须大于背景
    private void moveToEdge(float dx, float dy) {
        Log.d(TAG, "moveToEdge: getTranslateX():" + getTranslateX() + ", dx:" + dx);
        //向右滑动
        if (dx > 0) {
            if (getTranslateX() <= 0) {
                if (getTranslateX() + dx > 0) {
                    dx = -getMatrixScaleX();
                }
            }
        } else {   //向左滑动
            float currentSeatBitmapWidth = sceneBitmap.getWidth() * getMatrixScaleX();
            if (getTranslateX() < 0) {
                if (-dx - getTranslateX() + getWidth() > currentSeatBitmapWidth) {
                    dx = -currentSeatBitmapWidth - getTranslateX() + getWidth();
                }
            }
        }

        //向下滑动
        if (dy > 0) {
            if (getTranslateY() <= 0) {
                if (getTranslateY() + dy > 0) {
                    dy = -getMatrixScaleY();
                }
            }
        } else {   //向上滑动
            float currentSeatBitmapHeight = sceneBitmap.getHeight() * getMatrixScaleY();
            if (getTranslateY() < 0) {
                if (-dy - getTranslateY() + getHeight() > currentSeatBitmapHeight) {
                    dy = -currentSeatBitmapHeight - getTranslateY() + getHeight();
                }
            }
        }
        matrix.postTranslate(dx, dy);
    }


    ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            if (sceneBitmap == null) {
                return false;
            }

            isScale = true;
            float scaleFactor = detector.getScaleFactor();  //新的缩放比例
            if (getMatrixScaleY() * scaleFactor > mInitScale * 2) {
                scaleFactor = mInitScale * 2 / getMatrixScaleY();
            }

            if (getMatrixScaleY() * scaleFactor < mInitScale) {
                scaleFactor = mInitScale / getMatrixScaleY();
            }
            matrix.postScale(scaleFactor, scaleFactor);
            if (scaleFactor < 1) {   //缩小
                float dx = 0;
                float dy = 0;
                if (getWidth() - getTranslateX() > sceneBitmap.getWidth() * getMatrixScaleX()) {
                    dx = getWidth() - (sceneBitmap.getWidth() * getMatrixScaleX() + getTranslateX());
                }
                if (getHeight() - getTranslateY() > sceneBitmap.getHeight() * getMatrixScaleY()) {
                    dy = getHeight() - (sceneBitmap.getHeight() * getMatrixScaleY() + getTranslateY());
                }
                matrix.postTranslate(dx, dy);
            }
            invalidate();
            return true;
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            isScale = false;
        }
    });


    //单击事件拦截
    GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            Log.d(TAG, "onSingleTapConfirmed: onSingleTapConfirmed");
            if (sceneBitmap == null) {
                return super.onSingleTapConfirmed(e);
            }

            int x = (int) e.getX();
            int y = (int) e.getY();

            float zoom = getMatrixScaleX();
            float translateX = getTranslateX();
            float translateY = getTranslateY();
            float scaleX = zoom;
            float scaleY = zoom;

            int curX = (int) ((x - translateX) / scaleX);
            int curY = (int) ((y - translateY) / scaleY);

            if (pathCoordinateEventList != null) {
                for (int i = 0; i < pathCoordinateEventList.size(); i++) {
                    PathCoordinateEvent sceneBean = pathCoordinateEventList.get(i);
                    Path path = sceneBean.getPath();
                    boolean in = inPath(curX, curY, path);
                    if (in) {
                        if (onSceneClickListener != null) {
                            Toast.makeText(getContext(), "in paht " + in, Toast.LENGTH_SHORT).show();       //wwp test
                            onSceneClickListener.OnSceneClick(sceneBean.getActivation());
                            break;
                        }
                    }
                }
            }
            return super.onSingleTapConfirmed(e);
        }
    });

    private boolean inPath(int x, int y, Path path) {
        RectF rectF = new RectF();
        path.computeBounds(rectF, true);
        Region re = new Region();
        re.setPath(path, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom));
        return re.contains(x, y);
    }

    private class HandThread extends Thread {

        @Override
        public void run() {
            handler.sendEmptyMessage(SCENE_HAND_UP);
        }
    }


    //开始
    public void start() {
        if (handThread != null) {
            if (!handThread.isInterrupted()) {
                handThread.interrupt();
            }
            handThread = null;
        }
        handThread = new HandThread();
        handThread.start();
    }

    //停止
    public void stop() {
        if (handThread != null) {
            if (!handThread.isInterrupted()) {
                handThread.interrupt();
            }
            handThread = null;
        }
    }

    //设置场景图片 handX  handY 没有数据的时候默认为-1
    public void setSceneBitmap(Bitmap sceneBitmap, List<BubbleCoordinateEvent> pathCoordinate,
                               List<BubbleCoordinateEvent> bubbleCoordinate, int handX, int handY) {
        this.sceneBitmap = sceneBitmap;
        this.bubbleCoordinateList = bubbleCoordinate;
        this.pathCoordinateList = pathCoordinate;
        this.handX = handX;
        this.handY = handY;
        initCanvas();
        initSceneLocation();
        doSomething();
    }


    private float getTranslateX() {
        matrix.getValues(values);
        return values[2];
    }

    private float getTranslateY() {
        matrix.getValues(values);
        return values[5];
    }

    private float getMatrixScaleY() {
        matrix.getValues(values);
        return values[4];
    }

    private float getMatrixScaleX() {
        matrix.getValues(values);
        return values[Matrix.MSCALE_X];
    }

    //将本地资源图片转换为bitmap
    public Bitmap drawableToBitmap(Drawable drawable) {
        Bitmap bitmap = Bitmap.createBitmap(
                drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight(),
                drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
                        : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }


    // 根据手机的分辨率将dp的单位转成px(像素)
    public int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public interface OnSceneClickListener {
        void OnSceneClick(int activation);
    }

    public OnSceneClickListener getOnSceneClickListener() {
        return onSceneClickListener;
    }

    public void setOnSceneClickListener(OnSceneClickListener onSceneClickListener) {
        this.onSceneClickListener = onSceneClickListener;
    }
}
